# Updated by Wei on 2014/03/12 afternoon at school
# I had never seen a student whose working is so *, you are just ** ** enough
# Let's do the OR now
# Updated by Wei on 2014/03/11 afternoon at school
# continue to debug the OR evaluation scripts
# Updated by Wei on 2014/03/10 night at school
# the thinking is NOT right, I still need to know which set of postings contributed to the OR results. And let's find them out.
# Updated by Wei on 2014/03/08 afternoon at school
# Note: This might only for the case of the OR semantics

from __future__ import division
import os
import sys
from struct import *
from operator import itemgetter, attrgetter

print "Program Begins..."
numOfRelatedDocumentResultReturned = 0

# get all the related document results from the human judge side
humanJudgeDocumentResultDict1 = {}
# for pangolin:
# inputFileName1 = "/data/obukai/workspace_USE_SINCE_20140217Night/web-search-engine-wei-2014-March/data/qrels.tb04-tb06.top150_with_docID_added_termid_added_AND"
# for dodo:
inputFileName1 = "/home/diaosi/workspace/web-search-engine-wei-2014-March/data/qrels.tb04-tb06.top150_with_docID_added_termid_added_AND"
inputFileHandler = open(inputFileName1,"r")
for index,line in enumerate( inputFileHandler.readlines() ):
    lineElements = line.strip().split(" ")
    currentQID = lineElements[0]
    relevanceLabel = lineElements[3]
    currentDocID = lineElements[4]
    if relevanceLabel != "0":
        currentDocumentResultKey1 = currentQID + "_" + currentDocID
        if currentDocumentResultKey1 not in humanJudgeDocumentResultDict1:
            humanJudgeDocumentResultDict1[currentDocumentResultKey1] = 1
print "len(humanJudgeDocumentResultDict1):",len(humanJudgeDocumentResultDict1)

# get the document result(up to 100) from the my search system side
# become the accumulator
# key: currentQID

originalTOP10DocumentResultDict = {}
searchSystemDocumentResultDict1 = {}
# for pangolin:
# inputFileName2 = "/data/obukai/workspace_USE_SINCE_20140217Night/web-search-engine-wei-2014-March/polyIRIndexer/OR_top100_100%_tb04-06_final_with_termID_and_score_added"
# for dodo:
inputFileName2 = "/home/diaosi/workspace/web-search-engine-wei-2014-March/data/OR_top100_100%_tb04-06_final_with_termID_and_score_added"

inputFileHandler = open(inputFileName2,"r")
for line in inputFileHandler.readlines():
    lineElements = line.strip().split(" ")
    currentQID = lineElements[0]
    currentTrecID = lineElements[2]
    currentDocID = lineElements[-1]
    currentRank = int(lineElements[3])
    currentPartialBM25Score = float(lineElements[4])
    if currentQID not in searchSystemDocumentResultDict1:
        searchSystemDocumentResultDict1[currentQID] = {}
    currentDocumentResultKey1 = currentQID + "_" + currentDocID
    
    if currentDocumentResultKey1 not in searchSystemDocumentResultDict1[currentQID]:
        searchSystemDocumentResultDict1[currentQID][currentDocumentResultKey1] = 0.0

    if currentRank <= 10:
        if currentDocumentResultKey1 not in originalTOP10DocumentResultDict:
            originalTOP10DocumentResultDict[currentDocumentResultKey1] = 1
        else:
            pass
        
print "len(searchSystemDocumentResultDict1):",len(searchSystemDocumentResultDict1)
print "len(originalTOP10DocumentResultDict):",len(originalTOP10DocumentResultDict)

#tempCounter = 0
#for currentQID in searchSystemDocumentResultDict1:
#    tempCounter += len(searchSystemDocumentResultDict1[currentQID])
#print "tempCounter:",tempCounter
inputFileHandler.close()

postingWithDocumentResultDict = {}
inputFileHandler = open(inputFileName2,"r")
for line in inputFileHandler.readlines():
    lineElements = line.strip().split(" ")
    currentQID = lineElements[0]
    currentDocID = lineElements[-1]
    currentDocumentResultKey = currentQID + "_" + currentDocID  
    postingInfoList = lineElements[6:-1]
    numOfPostingInfos = int(len(postingInfoList) / 2)
    base = 0
    for i in range(0,numOfPostingInfos):
        currentTermID = postingInfoList[base]
        currentTermScore = float(postingInfoList[base+1])
        currentPostingKey = currentTermID + "_" + currentDocID
        if currentPostingKey not in postingWithDocumentResultDict:
            postingWithDocumentResultDict[currentPostingKey] = []
            postingWithDocumentResultDict[currentPostingKey].append(currentDocumentResultKey)
        else:
            postingWithDocumentResultDict[currentPostingKey].append(currentDocumentResultKey)
            # debug
            # print currentPostingKey,postingWithDocumentResultDict[currentPostingKey]
            # exit(1)
            #print "the posting has been contributed to multiple document results."
            #print "currentPostingKey:",currentPostingKey
            #print "currentDocumentResultKey:",currentDocumentResultKey
            #exit(1)
        base += 2

tempCounter = 0
for postingKey in postingWithDocumentResultDict:
    print postingKey,postingWithDocumentResultDict[postingKey]
    tempCounter += 1
    if tempCounter == 10:
        break

print "len(postingWithDocumentResultDict):",len(postingWithDocumentResultDict)

TOTAL_NUM_OF_POSTINGS = 6451948010
numOfPostingNeededToBePoppedAtDebugPercentage = 5000000
numOfPostingNeededToBePoppedAt1Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.01)
numOfPostingNeededToBePoppedAt3Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.03)
numOfPostingNeededToBePoppedAt5Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.05)
numOfPostingNeededToBePoppedAt10Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.1)
numOfPostingNeededToBePoppedAt15Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.15)
numOfPostingNeededToBePoppedAt20Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.2)
numOfPostingNeededToBePoppedAt30Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.3)
numOfPostingNeededToBePoppedAt40Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.4)
numOfPostingNeededToBePoppedAt50Percentage = int(TOTAL_NUM_OF_POSTINGS * 0.5)
print "numOfPostingNeededToBePoppedAtDebugPercentage:",numOfPostingNeededToBePoppedAtDebugPercentage
print "numOfPostingNeededToBePoppedAt1Percentage:",numOfPostingNeededToBePoppedAt1Percentage
print "numOfPostingNeededToBePoppedAt3Percentage:",numOfPostingNeededToBePoppedAt3Percentage
print "numOfPostingNeededToBePoppedAt5Percentage:",numOfPostingNeededToBePoppedAt5Percentage
print "numOfPostingNeededToBePoppedAt10Percentage:",numOfPostingNeededToBePoppedAt10Percentage
print "numOfPostingNeededToBePoppedAt15Percentage:",numOfPostingNeededToBePoppedAt15Percentage
print "numOfPostingNeededToBePoppedAt20Percentage:",numOfPostingNeededToBePoppedAt20Percentage
print "numOfPostingNeededToBePoppedAt30Percentage:",numOfPostingNeededToBePoppedAt30Percentage
print "numOfPostingNeededToBePoppedAt40Percentage:",numOfPostingNeededToBePoppedAt40Percentage
print "numOfPostingNeededToBePoppedAt50Percentage:",numOfPostingNeededToBePoppedAt50Percentage
numOfBytes = 0
numOfPostingPopped = 0
numOfPostingBeInTOP10 = 0

# for pangolin:
# N/A
# for dodo:
# inputFileName3 = "/home/diaosi/workspace/web-search-engine-wei-2014-March/results/allPostingsBeingPopped20140321Morning_weight_0_WHOLE"
# inputFileName3 = "/home/diaosi/workspace/web-search-engine-wei-2014-March/results/allPostingsBeingPopped20140320Afternoon_weight_1_WHOLE"
inputFileName3 = "/home/diaosi/workspace/web-search-engine-wei-2014-March/results/allPostingsBeingPopped20140320Afternoon_weight_50_WHOLE"

print "len(sys.argv):",len(sys.argv)
if len(sys.argv) != 2:
    print "Illegal # of arguments"
    print "Usage: python programName.py all_postings_being_popped_file"
    exit(1)

# the OLD version
# inputFileHandler = open(inputFileName3,"rb")
# print "inputFileName1:",inputFileName1
# print "inputFileName2:",inputFileName2
# print "inputFileName3:",inputFileName3
# statinfo = os.stat(inputFileName3)

# the current version
inputFileHandler = open(sys.argv[1],"rb")
print "inputFileName1:",inputFileName1
print "inputFileName2:",inputFileName2
print "--->posting file to evaluate:",sys.argv[1]
statinfo = os.stat(sys.argv[1])

fileSize = statinfo.st_size
print "file size:",fileSize
numOfResultsReturnedCountedUpTo10 = 0

while numOfBytes < fileSize:
    # old version
    # each time, just read the info of ONE posting, too few
    # byteString = inputFileHandler.read(4 + 4 + 4)
    # (termID,docID,currentProbability) = unpack( "2I1f", byteString)
    
    # current version
    # each time, read the info of 1M postings
    byteStringBuffer = inputFileHandler.read( 1000000 * 16)
    byteStringBufferIndexPosition = 0
    for i in range(0,1000000):
        byteString = byteStringBuffer[byteStringBufferIndexPosition:byteStringBufferIndexPosition+16]
        byteStringBufferIndexPosition += 16
        (termID,docID,currentProbability,impactScore) = unpack( "2I2f", byteString)
        postingKey = str(termID) + "_" + str(docID)
        # debug
        # print "postingKey:",postingKey
        # print termID,docID,currentProbability,impactScore
        if postingKey in postingWithDocumentResultDict:
            # interesting issue solved
            # print "touched."
            for currentDocumentResultKey in postingWithDocumentResultDict[postingKey]:
                currentQID = currentDocumentResultKey.strip().split("_")[0]
                searchSystemDocumentResultDict1[currentQID][currentDocumentResultKey] += impactScore
                # tempCounter += 1

        if numOfPostingPopped == numOfPostingNeededToBePoppedAtDebugPercentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt1Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt3Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt5Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt10Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt15Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt20Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt30Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt40Percentage or numOfPostingPopped == numOfPostingNeededToBePoppedAt50Percentage:
            numOfResultsReturnedCountedUpTo10 = 0
            numOfRelatedDocumentResultReturned = 0
            numOfOriginalTOP10DocumentResultReturned = 0
            numOfRelevantTOP10DocumentResultReturned = 0
            documentResultToCompare = {}
            for currentQID in searchSystemDocumentResultDict1:
                if currentQID not in documentResultToCompare:
                    documentResultToCompare[currentQID] = []
                for currentDocumentResultKey in searchSystemDocumentResultDict1[currentQID]:
                    if searchSystemDocumentResultDict1[currentQID][currentDocumentResultKey] != 0.0:
                        documentResultCandidateTuple = (currentDocumentResultKey,searchSystemDocumentResultDict1[currentQID][currentDocumentResultKey])
                        documentResultToCompare[currentQID].append(documentResultCandidateTuple)
                documentResultToCompare[currentQID].sort(cmp=None, key=itemgetter(1), reverse=True)
                
                # print currentQID,len(documentResultToCompare[currentQID])
                
                # debug
                # if currentQID == "804" or currentQID == "835":
                #    print currentQID,len(documentResultToCompare[currentQID])
                #    print currentQID,documentResultToCompare[currentQID]
                
            
            for currentQID in documentResultToCompare:
                
                listUpperBound = 0
                if len(documentResultToCompare[currentQID]) >= 10:
                    listUpperBound = 10
                else:
                    listUpperBound = len(documentResultToCompare[currentQID])
                
                currentRankForEval = 0
                for documentResultCandidateTuple in documentResultToCompare[currentQID][:listUpperBound]:
                    (currentDocumentResultKey,score) = documentResultCandidateTuple
                    numOfResultsReturnedCountedUpTo10 += 1
                    currentQIDForEval = currentDocumentResultKey.strip().split("_")[0]
                    currentDocIDForEval = currentDocumentResultKey.strip().split("_")[1]
                    currentRankForEval += 1
                    outputLineForEval = str(currentQIDForEval) + " " + "Q0" + " " + str(currentDocIDForEval) + " " + str(currentRankForEval) + " " + str(score) + " " + "PolyIRTKDebug" + "\n"
                    print "----->",outputLineForEval,
                    
                    if currentDocumentResultKey in originalTOP10DocumentResultDict:
                        numOfOriginalTOP10DocumentResultReturned += 1
                    
                    if currentDocumentResultKey in humanJudgeDocumentResultDict1:
                        numOfRelatedDocumentResultReturned += 1
                    
                    if currentDocumentResultKey in originalTOP10DocumentResultDict and currentDocumentResultKey in humanJudgeDocumentResultDict1:
                        numOfRelevantTOP10DocumentResultReturned += 1
                
                # print currentQID,len(documentResultToCompare[currentQID][:listUpperBound])
                
                # debug
                # if currentQID == "804" or currentQID == "835":
                #    print currentQID,len(documentResultToCompare[currentQID][:listUpperBound])
                #    print currentQID,documentResultToCompare[currentQID][:listUpperBound]
                
                
            print "numOfRelevantDocumentResultReturned:",numOfRelatedDocumentResultReturned,"out of",len(humanJudgeDocumentResultDict1),"human judged related documents"
            print "numOfRelevantDocumentResultReturned:",numOfRelatedDocumentResultReturned,"out of",str(numOfResultsReturnedCountedUpTo10),"returned results up to 10 by system"
            print "numOfOriginalTOP10DocumentResultReturned:",numOfOriginalTOP10DocumentResultReturned,"out of",str(numOfResultsReturnedCountedUpTo10),"returned results up to 10 by system"
            print "numOfRelevantTOP10DocumentResultReturned:",numOfRelevantTOP10DocumentResultReturned,"among",numOfRelatedDocumentResultReturned,"relevant document results"
            print "numOfPostingPopped:",numOfPostingPopped
            # print "tempCounter:",tempCounter
            
            
        numOfBytes += 12
        numOfPostingPopped += 1
        if numOfPostingPopped % 1000000 == 0:
            print str(numOfPostingPopped),"postings have been examined."

inputFileHandler.close()
print "Program Ends."





